From: awilliam@xenbuild2.aw Date: Tue, 20 Mar 2007 15:32:24 +0000 (-0600) Subject: [IA64] fix access rights in VHPT when itr.ar!=dtr.ar X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~15285 X-Git-Url: https://dgit.raspbian.org/%22http:/www.example.com/cgi/%22https:/%22bookmarks://%22Dat/%22http:/www.example.com/cgi/%22https:/%22bookmarks:/%22Dat?a=commitdiff_plain;h=1264150f8c2f288986f2e79bc45cc89f129b62c8;p=xen.git [IA64] fix access rights in VHPT when itr.ar!=dtr.ar This is a workaround patch for Windows 2003 Server. Windows (vcpu>=2) set itr[1].ar=3(RWX) but dtr[1].ar=2(RW). It causes an impossible INST_ACCESS_RIGHTS interruption via VHPT which is used for emulating TR. Surprisingly, windows ordinarily accepts this interruption. But windows sometimes crashes with the message 'PANIC_STACK_SWITCH' owing to this interruption. Signed-off-by: Kouya Shimura --- diff --git a/xen/arch/ia64/vmx/vmx_process.c b/xen/arch/ia64/vmx/vmx_process.c index 5e40330476..4ee7d4e805 100644 --- a/xen/arch/ia64/vmx/vmx_process.c +++ b/xen/arch/ia64/vmx/vmx_process.c @@ -92,6 +92,11 @@ void vmx_reflect_interruption(u64 ifa, u64 isr, u64 iim, switch (vec) { + case 22: // IA64_INST_ACCESS_RIGHTS_VECTOR + if (vhpt_access_rights_fixup(vcpu, ifa, 0)) + return; + break; + case 25: // IA64_DISABLED_FPREG_VECTOR if (FP_PSR(vcpu) & IA64_PSR_DFH) { diff --git a/xen/arch/ia64/vmx/vtlb.c b/xen/arch/ia64/vmx/vtlb.c index 3b6c5377b7..9f01627602 100644 --- a/xen/arch/ia64/vmx/vtlb.c +++ b/xen/arch/ia64/vmx/vtlb.c @@ -196,6 +196,37 @@ void thash_vhpt_insert(VCPU *v, u64 pte, u64 itir, u64 va, int type) ia64_srlz_i(); } } + +int vhpt_access_rights_fixup(VCPU *v, u64 ifa, int is_data) +{ + thash_data_t *trp, *data; + u64 ps, tag, mask; + + trp = __vtr_lookup(v, ifa, is_data); + if (trp) { + ps = _REGION_PAGE_SIZE(ia64_get_rr(ifa)); + if (trp->ps < ps) + return 0; + ifa = PAGEALIGN(ifa, ps); + data = (thash_data_t *)ia64_thash(ifa); + tag = ia64_ttag(ifa); + do { + if (data->etag == tag) { + mask = trp->page_flags & PAGE_FLAGS_AR_PL_MASK; + if (mask != (data->page_flags & PAGE_FLAGS_AR_PL_MASK)) { + data->page_flags &= ~PAGE_FLAGS_AR_PL_MASK; + data->page_flags |= mask; + machine_tlb_purge(ifa, ps); + return 1; + } + return 0; + } + data = data->next; + } while(data); + } + return 0; +} + /* * vhpt lookup */ diff --git a/xen/include/asm-ia64/vmmu.h b/xen/include/asm-ia64/vmmu.h index 905d122f68..84c23c2dfd 100644 --- a/xen/include/asm-ia64/vmmu.h +++ b/xen/include/asm-ia64/vmmu.h @@ -291,6 +291,7 @@ extern int thash_lock_tc(thash_cb_t *hcb, u64 va, u64 size, int rid, char cl, in #define ITIR_RV_MASK (((1UL<<32)-1)<<32 | 0x3) #define PAGE_FLAGS_RV_MASK (0x2 | (0x3UL<<50)|(((1UL<<11)-1)<<53)) +#define PAGE_FLAGS_AR_PL_MASK ((0x7UL<<9)|(0x3UL<<7)) extern u64 machine_ttag(PTA pta, u64 va); extern u64 machine_thash(PTA pta, u64 va); extern void purge_machine_tc_by_domid(domid_t domid); @@ -309,6 +310,7 @@ extern u64 translate_phy_pte(struct vcpu *v, u64 *pte, u64 itir, u64 va); extern void thash_vhpt_insert(struct vcpu *v, u64 pte, u64 itir, u64 ifa, int type); extern u64 guest_vhpt_lookup(u64 iha, u64 *pte); +extern int vhpt_access_rights_fixup(struct vcpu *v, u64 ifa, int is_data); static inline void vmx_vcpu_set_tr (thash_data_t *trp, u64 pte, u64 itir, u64 va, u64 rid) {